<?php

/**
 * @file classes/journal/DMNTDAO.inc.php
 *
 * Copyright (c) 2003-2012 John Willinsky
 * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
 *
 * @class DMNTDAO
 * @ingroup journal
 * @see DMNT
 *
 * @brief Operations for retrieving and modifying DMNT objects.
 */

// $Id$

define('DMNT_FIELD_MANT', 'MANT');
define('DMNT_FIELD_TENNT', 'TENNT');
define('DMNT_FIELD_NONE', null);



import ('classes.acct.DMNT');

class DMNTDAO extends DAO {
	var $cache;

	function _cacheMiss(&$cache, $id) {
		$DMNT =& $this->getDMNT($id, null, false);
		$cache->setCache($id, $DMNT);
		return $DMNT;
	}

	function &_getCache() {
		if (!isset($this->cache)) {
			$cacheManager =& CacheManager::getManager();
			$this->cache =& $cacheManager->getObjectCache('DMNT', 0, array(&$this, '_cacheMiss'));
		}
		return $this->cache;
	}

 	function &getDMNT($MANT, $DaoFac = false, $combo = false) {
		if (isset($MANT))
			$result =& $this->retrieve(
				'SELECT * FROM DMNT WHERE MANT = ? ORDER BY MANT', $MANT
			);
		else
			$result =& $this->retrieve(
				"SELECT * FROM DMNT WHERE MANT !='' ORDER BY MANT");

		$sectionsIterator = new DAOResultFactory($result, $this, '_returnDMNTFromRow');

		if ($DaoFac)
			return $sectionsIterator;
		else if (!$combo)
		{
			$returner = null;
			if ($result->RecordCount() != 0) {
				$returner =& $this->_returnDMNTFromRow($result->GetRowAssoc(false));
			}

			$result->Close();
			unset($result);
			return $returner;
		}


		$sections = $returner ;

		while (($section =& $sectionsIterator->next())) {
			$sections[$section->getMANT()] = $section->getMANT()."-".$section->gettennt();
			unset($section);
		}
		return $sections;
	}


 	function &getDSMANT($MANT) {
		if (isset($MANT))
			$result =& $this->retrieve(
				'SELECT * FROM DMNT WHERE MANT = ? ORDER BY MANT', $MANT
			);
		else
			$result =& $this->retrieve(
				"SELECT * FROM DMNT WHERE MANT !='' ORDER BY MANT");

		$sectionsIterator = new DAOResultFactory($result, $this, '_returnDMNTFromRow');

		$sections = $returner ;

		while (($section =& $sectionsIterator->next())) {
			$sections[] = $section->getmant()."-".$section->gettennt();
			unset($section);
		}
		//var_dump($sections);
		return $sections;
	}
	

 	function &getDSMANT_MA($MANT) {
		if (isset($MANT))
			$result =& $this->retrieve(
				'SELECT * FROM DMNT WHERE MANT = ? ORDER BY MANT', $MANT
			);
		else
			$result =& $this->retrieve(
				"SELECT * FROM DMNT WHERE MANT !='' ORDER BY MANT");

		$sectionsIterator = new DAOResultFactory($result, $this, '_returnDMNTFromRow');

		$sections = $returner ;

		while (($section =& $sectionsIterator->next())) {
			$sections[$section->getmant()] = $section->getmant();
			unset($section);
		}
		//var_dump($sections);
		return $sections;
	}


	function &_returnDMNTFromRow(&$row) {
		$DMNT = new DMNT($row['mant'], $row['tennt']);
		return $DMNT;
	}


	function &getDMNTSearch($searchType = null, $search = null, $searchMatch = null) {

		$paramArray = array();
		$searchSql = '';

		$searchTypeMap = array(
			DMNT_FIELD_MANT => 'DMNT.mant',
			DMNT_FIELD_TENNT => 'DMNT.tennt'

		);

		if (!empty($search) && isset($searchTypeMap[$searchType])) {

			$fieldName = $searchTypeMap[$searchType];
			switch ($searchMatch) {
				case 'is':
					$searchSql = "AND LOWER($fieldName) = LOWER(?)";
					$paramArray[] = $search;
					break;
				case 'contains':
					$searchSql = "AND LOWER($fieldName) LIKE LOWER(?)";
					$paramArray[] = '%' . $search . '%';
					break;
				case 'startsWith':
					$searchSql = "AND LOWER($fieldName) LIKE LOWER(?)";
					$paramArray[] = $search . '%';
					break;
			}
		}
//		elseif (!empty($search)) switch ($searchType) {
//			case USER_FIELD_USERID:
//				$searchSql = 'AND u.user_id=?';
//				$paramArray[] = $search;
//				break;
//			case USER_FIELD_INITIAL:
//				$searchSql = 'AND LOWER(u.last_name) LIKE LOWER(?)';
//				$paramArray[] = $search . '%';
//				break;
//		}

		//$searchSql .= ($sortBy?(' ORDER BY ' . $this->getSortMapping($sortBy) . ' ' . $this->getDirectionMapping($sortDirection)) : '');
		$result =& $this->retrieve(
				"SELECT * FROM DMNT WHERE MANT !='' ". $searchSql. " ORDER BY MANT",
			$paramArray
		);

		$returner = new DAOResultFactory($result, $this, '_returnDMNTFromRow');
	
		return $returner;
	}



	function deleteTKByMa($DMNTId) {
		return $this->update(
			'DELETE FROM DMNT WHERE MANT = ? ',
			array($DMNTId)
			);
	}






	

	/**
	 * Retrieve a DMNT by abbreviation.
	 * @param $DMNTAbbrev string
	 * @param $locale string optional
	 * @return DMNT
	 */
	function &getDMNTByAbbrev($DMNTAbbrev, $journalId, $locale = null) {
		$sql = 'SELECT s.* FROM DMNT s, DMNT_settings l WHERE l.DMNT_id = s.DMNT_id AND l.setting_name = ? AND l.setting_value = ? AND s.journal_id = ?';
		$params = array('abbrev', $DMNTAbbrev, $journalId);
		if ($locale !== null) {
			$sql .= ' AND l.locale = ?';
			$params[] = $locale;
		}

		$result =& $this->retrieve($sql, $params);

		$returner = null;
		if ($result->RecordCount() != 0) {
			$returner =& $this->_returnDMNTFromRow($result->GetRowAssoc(false));
		}

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Retrieve a DMNT by title.
	 * @param $DMNTTitle string
	 * @return DMNT
	 */
	function &getDMNTByTitle($DMNTTitle, $journalId, $locale = null) {
		$sql = 'SELECT s.* FROM DMNT s, DMNT_settings l WHERE l.DMNT_id = s.DMNT_id AND l.setting_name = ? AND l.setting_value = ? AND s.journal_id = ?';
		$params = array('title', $DMNTTitle, $journalId);
		if ($locale !== null) {
			$sql .= ' AND l.locale = ?';
			$params[] = $locale;
		}

		$result =& $this->retrieve($sql, $params);

		$returner = null;
		if ($result->RecordCount() != 0) {
			$returner =& $this->_returnDMNTFromRow($result->GetRowAssoc(false));
		}

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Retrieve a DMNT by title and abbrev.
	 * @param $DMNTTitle string
	 * @param $DMNTAbbrev string
	 * @param $locale string optional
	 * @return DMNT
	 */
	function &getDMNTByTitleAndAbbrev($DMNTTitle, $DMNTAbbrev, $journalId, $locale) {
		$sql = 'SELECT s.* FROM DMNT s, DMNT_settings l1, DMNT_settings l2 WHERE l1.DMNT_id = s.DMNT_id AND l2.DMNT_id = s.DMNT_id AND l1.setting_name = ? AND l2.setting_name = ? AND l1.setting_value = ? AND l2.setting_value = ? AND s.journal_id = ?';
		$params = array('title', 'abbrev', $DMNTTitle, $DMNTAbbrev, $journalId);
		if ($locale !== null) {
			$sql .= ' AND l1.locale = ? AND l2.locale = ?';
			$params[] = $locale;
			$params[] = $locale;
		}

		$result =& $this->retrieve($sql, $params);

		$returner = null;
		if ($result->RecordCount() != 0) {
			$returner =& $this->_returnDMNTFromRow($result->GetRowAssoc(false));
		}

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Internal function to return a DMNT object from a row.
	 * @param $row array
	 * @return DMNT
	 */

//	/**
//	 * Get the list of fields for which data can be localized.
//	 * @return array
//	 */
//	function getLocaleFieldNames() {
//		return array('title', 'abbrev', 'policy', 'identifyType');
//	}
//
//	/**
//	 * Update the localized fields for this table
//	 * @param $DMNT object
//	 */
	function updateLocaleFields(&$DMNT) {
		$this->updateDataObjectSettings('DMNT_settings', $DMNT, array(
			'DMNT_id' => $DMNT->getId()
		));
	}

	/**
	 * Insert a new DMNT.
	 * @param $DMNT DMNT
	 */
	function insertDMNT(&$DMNT) {
		$this->update(
			'INSERT INTO DMNT
				(MANT, tennt)
				VALUES
				(?, ?)',
			array(
				$DMNT->getMANT(),
				$DMNT->gettennt()
			)
		);

		$DMNT->setId($this->getInsertDMNTId());
		$this->updateLocaleFields($DMNT);
		return $DMNT->getId();
	}

	/**
	 * Update an existing DMNT.
	 * @param $DMNT DMNT
	 */
	function updateDMNT(&$DMNT) {
		$returner = $this->update(
			'UPDATE DMNT
				SET
					MANT = ?,
					tennt = ?
				WHERE MANT = ?',
			array(
				$DMNT->getMANT(),
				$DMNT->gettennt(),
				$DMNT->getMANT()
			)
		);
		$this->updateLocaleFields($DMNT);
		return $returner;
	}

	/**
	 * Delete a DMNT.
	 * @param $DMNT DMNT
	 */
	function deleteDMNT(&$DMNT) {
		return $this->deleteDMNTById($DMNT->getId(), $DMNT->getJournalId());
	}

	/**
	 * Delete a DMNT by ID.
	 * @param $DMNTId int
	 * @param $journalId int optional
	 */

	/**
	 * Delete DMNT by journal ID
	 * NOTE: This does not delete dependent entries EXCEPT from DMNT_editors. It is intended
	 * to be called only when deleting a journal.
	 * @param $journalId int
	 */
	function deleteDMNTByJournal($journalId) {
		$DMNT =& $this->getJournalDMNT($journalId);
		while (($DMNT =& $DMNT->next())) {
			$this->deleteDMNT($DMNT);
			unset($DMNT);
		}
	}

	/**
	 * Retrieve an array associating all DMNT editor IDs with
	 * arrays containing the DMNT they edit.
	 * @return array editorId => array(DMNT they edit)
	 */
	function &getEditorDMNT($journalId) {
		$returner = array();

		$result =& $this->retrieve(
			'SELECT s.*, se.user_id AS editor_id FROM DMNT_editors se, DMNT s WHERE se.DMNT_id = s.DMNT_id AND s.journal_id = se.journal_id AND s.journal_id = ?',
			$journalId
		);

		while (!$result->EOF) {
			$row = $result->GetRowAssoc(false);
			$DMNT =& $this->_returnDMNTFromRow($row);
			if (!isset($returner[$row['editor_id']])) {
				$returner[$row['editor_id']] = array($DMNT);
			} else {
				$returner[$row['editor_id']][] = $DMNT;
			}
			$result->moveNext();
		}

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Retrieve all DMNT in which articles are currently published in
	 * the given issue.
	 * @return array
	 */
	function &getDMNTForIssue($issueId) {
		$returner = array();

		$result =& $this->retrieve(
			'SELECT DISTINCT s.*, COALESCE(o.seq, s.seq) AS DMNT_seq FROM DMNT s, published_articles pa, articles a LEFT JOIN custom_DMNT_orders o ON (a.DMNT_id = o.DMNT_id AND o.issue_id = ?) WHERE s.DMNT_id = a.DMNT_id AND pa.article_id = a.article_id AND pa.issue_id = ? ORDER BY DMNT_seq',
			array($issueId, $issueId)
		);

		while (!$result->EOF) {
			$row = $result->GetRowAssoc(false);
			$returner[] =& $this->_returnDMNTFromRow($row);
			$result->moveNext();
		}

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Retrieve all DMNT for a journal.
	 * @return DAOResultFactory containing DMNT ordered by sequence
	 */
	function &getJournalDMNT($journalId, $rangeInfo = null) {
		$result =& $this->retrieveRange(
			'SELECT * FROM DMNT WHERE journal_id = ? ORDER BY seq',
			$journalId, $rangeInfo
		);

		$returner = new DAOResultFactory($result, $this, '_returnDMNTFromRow');
		return $returner;
	}

	/**
	 * Retrieve the IDs and titles of the DMNT for a journal in an associative array.
	 * @return array
	 */
	function &getDMNTTitles($journalId, $submittableOnly = false) {
		$DMNT = array();

		$DMNTIterator =& $this->getJournalDMNT($journalId);
		while (($DMNT =& $DMNTIterator->next())) {
			if ($submittableOnly) {
				if (!$DMNT->getEditorRestricted()) {
					$DMNT[$DMNT->getId()] = $DMNT->getLocalizedTitle();
				}
			} else {
				$DMNT[$DMNT->getId()] = $DMNT->getLocalizedTitle();
			}
			unset($DMNT);
		}

		return $DMNT;
	}

	/**
	 * Check if a DMNT exists with the specified ID.
	 * @param $DMNTId int
	 * @param $journalId int
	 * @return boolean
	 */
	function DMNTExists($DMNTId, $journalId) {
		$result =& $this->retrieve(
			'SELECT COUNT(*) FROM DMNT WHERE DMNT_id = ? AND journal_id = ?',
			array($DMNTId, $journalId)
		);
		$returner = isset($result->fields[0]) && $result->fields[0] == 1 ? true : false;

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Sequentially renumber DMNT in their sequence order.
	 * @param $journalId int
	 */
	function resequenceDMNT($journalId) {
		$result =& $this->retrieve(
			'SELECT DMNT_id FROM DMNT WHERE journal_id = ? ORDER BY seq',
			$journalId
		);

		for ($i=1; !$result->EOF; $i++) {
			list($DMNTId) = $result->fields;
			$this->update(
				'UPDATE DMNT SET seq = ? WHERE DMNT_id = ?',
				array(
					$i,
					$DMNTId
				)
			);

			$result->moveNext();
		}

		$result->close();
		unset($result);
	}

	/**
	 * Get the ID of the last inserted DMNT.
	 * @return int
	 */
	function getInsertDMNTId() {
		return $this->getInsertId('DMNT', 'DMNT_id');
	}

	/**
	 * Delete the custom ordering of an issue's DMNT.
	 * @param $issueId int
	 */
	function deleteCustomDMNTOrdering($issueId) {
		return $this->update(
			'DELETE FROM custom_DMNT_orders WHERE issue_id = ?', $issueId
		);
	}

	/**
	 * Delete a DMNT from the custom DMNT order table.
	 * @param $issueId int
	 * @param $DMNTId int
	 */
	function deleteCustomDMNT($issueId, $DMNTId) {
		$sequence = $this->getCustomDMNTOrder($issueId, $DMNTId);

		$this->update(
			'DELETE FROM custom_DMNT_orders WHERE issue_id = ? AND DMNT_id = ?', array($issueId, $DMNTId)
		);

		// Reduce the DMNT order of every successive DMNT by one
		$this->update(
			'UPDATE custom_DMNT_orders SET seq = seq - 1 WHERE issue_id = ? AND seq > ?', array($issueId, $sequence)
		);
	}

	/**
	 * Sequentially renumber custom DMNT orderings in their sequence order.
	 * @param $issueId int
	 */
	function resequenceCustomDMNTOrders($issueId) {
		$result =& $this->retrieve(
			'SELECT DMNT_id FROM custom_DMNT_orders WHERE issue_id = ? ORDER BY seq',
			$issueId
		);

		for ($i=1; !$result->EOF; $i++) {
			list($DMNTId) = $result->fields;
			$this->update(
				'UPDATE custom_DMNT_orders SET seq = ? WHERE DMNT_id = ? AND issue_id = ?',
				array($i, $DMNTId, $issueId)
			);

			$result->moveNext();
		}

		$result->close();
		unset($result);
	}

	/**
	 * Check if an issue has custom DMNT ordering.
	 * @param $issueId int
	 * @return boolean
	 */
	function customDMNTOrderingExists($issueId) {
		$result =& $this->retrieve(
			'SELECT COUNT(*) FROM custom_DMNT_orders WHERE issue_id = ?',
			$issueId
		);
		$returner = isset($result->fields[0]) && $result->fields[0] == 0 ? false : true;

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Get the custom DMNT order of a DMNT.
	 * @param $issueId int
	 * @param $DMNTId int
	 * @return int
	 */
	function getCustomDMNTOrder($issueId, $DMNTId) {
		$result =& $this->retrieve(
			'SELECT seq FROM custom_DMNT_orders WHERE issue_id = ? AND DMNT_id = ?',
			array($issueId, $DMNTId)
		);

		$returner = null;
		if (!$result->EOF) {
			list($returner) = $result->fields;
		}
		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Import the current DMNT orders into the specified issue as custom
	 * issue orderings.
	 * @param $issueId int
	 */
	function setDefaultCustomDMNTOrders($issueId) {
		$result =& $this->retrieve(
			'SELECT s.DMNT_id FROM DMNT s, issues i WHERE i.journal_id = s.journal_id AND i.issue_id = ? ORDER BY seq',
			$issueId
		);

		for ($i=1; !$result->EOF; $i++) {
			list($DMNTId) = $result->fields;
			$this->insertCustomDMNTOrder($issueId, $DMNTId, $i);
			$result->moveNext();
		}

		$result->close();
		unset($result);
	}

	/**
	 * INTERNAL USE ONLY: Insert a custom DMNT ordering
	 * @param $issueId int
	 * @param $DMNTId int
	 * @param $seq int
	 */
	function insertCustomDMNTOrder($issueId, $DMNTId, $seq) {
		$this->update(
			'INSERT INTO custom_DMNT_orders (DMNT_id, issue_id, seq) VALUES (?, ?, ?)',
			array(
				$DMNTId,
				$issueId,
				$seq
			)
		);
	}

	/**
	 * Move a custom issue ordering up or down, resequencing as necessary.
	 * @param $issueId int
	 * @param $DMNTId int
	 * @param $newPos int The new position (0-based) of this DMNT
	 * @param $up boolean Whether we're moving the DMNT up or down
	 */
	function moveCustomDMNTOrder($issueId, $DMNTId, $newPos, $up) {
		$this->update(
			'UPDATE custom_DMNT_orders SET seq = ? ' . ($up?'-':'+') . ' 0.5 WHERE issue_id = ? AND DMNT_id = ?',
			array($newPos, $issueId, $DMNTId)
		);
		$this->resequenceCustomDMNTOrders($issueId);
	}
}

?>
